[iOS 8] HealthKitを実装する(1) HealthKit簡易リファレンス
HealthKitを使う
HealthKitを使ったアプリの実装方法について紹介します。
HealthKitではiOS 8ユーザーの健康に関する情報を、アプリ間を跨いだ共有の保存領域(HealthStore)で永続化することができます。
あらかじめHealthKitで指定された値を各々のアプリケーションから永続化することで、プリインストールされている「ヘルスケア」から一括して参照することが出来ます。
HealthKitを実機で使う準備
Xcodeで作成したプロジェクトのHealthKitを有効にする必要があります。有効化はCapabilitiesのタブから行えます。
[Project] → [TARGETS (AppID)] → [Capabilities] → [HealthKit]
の順に選択して有効化して下さい。
HealthKitを使ったアプリをリリースする場合、iOS Dev CenterでApp IDを作成する際にHealthKitの有効化が必要です。
App ID作成時、忘れずにHealthKitの項目を有効化しましょう。
以上でHealthKitを実装する準備が整いました。
HealthKitが扱うデータ
先にも記述した通り、HealthKitで扱えるデータはあらかじめ決められています。健康に関するデータなら何でも扱えるという訳ではありません。
HealthStore
HealthKitで管理される保存領域をHealthStoreといいます。HealthStoreへのデータの読み書きにはユーザーの認証が必要です。
アプリケーションで、HealthStoreへのデータを読み書きする時に認証を求めるメソッドがあらかじめ用意されています。
この認証で、ユーザーは任意のデータの読み書きを制限することができます。
HealthStoreは以下のように生成します。
let healthStore: HKHealthStore = HKHealthStore()
HKObject
HealthKitで扱えるデータオブジェクトをHKObjectといいます。HealthKitとのデータのやり取りはこのHKObjectを介して行います。
HKObjectは以下の3つで構成されています。
-
UUID
HealthKitデータベースの一意な識別子を表します。
-
source
データが提供されたアプリの情報、もしくはデバイスの情報が入ります。
-
metadata
データ提供元のメタ情報が入ります。メタ情報はDictionary形式で、キーはNSString、値はNSString・NSNumber・NSDateが使えます。
HKUnit
データの単位を示します。例えば、扱うデータが体温だとすると、単位は「摂氏(℃)」となります。
HKUnitは以下のように生成します。
let unit: HKUnit! = HKUnit.degreeCelsiusUnit() // 単位 摂氏の生成 let unit: HKUnit! = HKUnit(fromString: "degC") // 単位 摂氏(degrees Celsius)の生成
単位専用のイニシャライザから生成する方法と、コンストラクタに文字列を指定して生成する方法の2パターンがあります。 それぞれの単位の生成方法についてはHKUnit.hをご覧下さい。
HKQuantity
データの値を示します。例えば、扱うデータが体温だとすると、値は「36.0」となります。
HKQuantity(値)を生成するためにはHKUnit(単位)が必要です。以下のように生成します。
let quantity: HKQuantity = HKQuantity(unit: myUnit, doubleValue: 36.0)
HKObjectType
HealthKitデータの種類を示します。データの種類を生成するメソッドは5つ用意されています。
class func quantityTypeForIdentifier(identifier: String!) -> HKQuantityType! class func categoryTypeForIdentifier(identifier: String!) -> HKCategoryType! class func characteristicTypeForIdentifier(identifier: String!) -> HKCharacteristicType! class func correlationTypeForIdentifier(identifier: String!) -> HKCorrelationType! class func workoutType() -> HKWorkoutType!
それぞれの種類の区分の詳細は以下の通りです。
HKQuantityType
身長・体重・体脂肪率・歩数・消費カロリー・心拍数・体温・栄養
主に数値で換算できる種類です。ほとんどのデータがこれに該当します。
HKCategoryType
2014/09/18 現在ではHKCategoryTypeIdentifierSleepAnalysisのみです。
睡眠に関する種類です。
HKCharacteristicType
生年月日・生物学的性別・血液型
ユーザーの情報です。医療分野で必要になりそうなデータです。2014/09/18 現在では3つのみです。
HKCorrelationType
2014/09/18 現在、HKCorrelationTypeIdentifierBloodPressureとHKCorrelationTypeIdentifierFoodの2つのみです。
相関関係のあるデータがこちらに該当すると思われます。
HKWorkoutType
2014/09/18 現在、HKWorkoutTypeIdentifierのみです。
トラッキングが必要なデータがこちらに該当すると思われます。
例えば、扱うデータが体温だとすると、種類は「HKQuantityType」となります。HKQuantityTypeを生成するには、何のデータを表すかのIDが必要です。以下のように生成します。
let quantityType: HKQuantityType! = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyTemperature)
quantityTypeForIdentifierメソッドの引数にIDを指定します。HKQuantityTypeIdentifierBodyTemperatureは体温のIDです。
それぞれのデータにIDの定数が割り振られています。HKQuantityTypeであればHKQuantityTypeIdentifierまで入力すれば、あとは補完から選べるでしょう。
HKSample
HKSampleはHKObjectを継承したクラスです。HealthStoreとのデータのやり取りをする際のデータを、より具体的に扱えるようにしたクラスです。
HKSampleは以下の3つで構成されています。
-
sampleType
どんなデータを扱うオブジェクトなのかを表します。
-
startDate
開始時刻が入ります。計測対象のデータによってはendDateと同じになります。
-
endDate
終了時刻が入ります。計測対象のデータによってはstartDateと同じになります。
データの種類によってHKSampleオブジェクトのサブクラスが用意されています。
HKQuantitySample
HKQuantityTypeのHKObjectです。各計測データは、HKQuantitySampleを介してHealthStoreとやり取りします。
HKCategorySample
HKCategoryTypeのHKObjectです。睡眠データは、HKCategorySampleを介してHeatlhStoreとやり取りします。
HKQuery
HKObjectをHelthStoreから問い合わせるためのクエリーです。
2014/09/18 現在、以下の7つが用意されています。
HKSampleQuery
永続化されたHKSampleオブジェクトをHealthStoreから問い合わせるクエリーです。
- Int limit
- [AnyObject]? sortDescriptors
をプロパティとして保持しています。使い方は後述の実装例を参考にして下さい。
HKObserverQuery
HealthStoreの値の変更を検知するためのクラスです。
コンストラクタにCompletionHandlerを指定して使います。
HKObserverQuery(sampleType: HKSampleType!, predicate: NSPredicate!, updateHandler: ((HKObserverQuery!, HKObserverQueryCompletionHandler!, NSError!) -> Void)!)
HealthStoreの対象のデータが刻々と変化する場合は、こちらのハンドラに登録しておけば変更時にCompletionHandlerが呼び出されます。
ハンドラ内でHKSampleQueryを実行すれば、検索をして値が変わっているかを確認する必要がなくなります。クエリの無駄な発行を抑えることが出来ます。
HKAnchoredObjectQuery
HealthStoreに永続化された値が他のアプリケーションによって更新された時、自分のアプリケーションのデータとの差分を取得できます。
こちらもコンストラクタにCompletionHandlerを指定して使います。
HKAnchoredObjectQuery(type: HKSampleType!, predicate: NSPredicate!, anchor: Int, limit: Int, completionHandler handler: ((HKAnchoredObjectQuery!, [AnyObject]!, Int, NSError!) -> Void)!)
複数のアプリを組み合わせて、同じデータを扱う場合には必要になりそうです。HealthStoreのデータはAnchorの連番によって管理されています。
anchor: Intにはどの時点からの差分を取得するか指定できます。0を指定すると全てのデータが取得できます。
CompletionHandler内で新しく渡されるnewAnchor: Intを保持しておけば、以降は差分データのみを取得できます。
HKObserverQueryと組み合わせることで、特定の時点からの値の変化を、余計な値を取得することなく監視することが出来ます。
HKStatisticsQuery
統計データを取得するために使います。
HKStatisticsQuery(quantityType: HKQuantityType!, quantitySamplePredicate: NSPredicate!, options: HKStatisticsOptions, completionHandler handler: ((HKStatisticsQuery!, HKStatistics!, NSError!) -> Void)!)
数値で計測できるデータのみを対象に限定されています。
第3引数にHKStatisticsOptionsを指定することによって、何を基準に取得するかを指定できます。
- None(指定なし)
- SeparateBySource(取得元)
- DiscreteAverage(平均値)
- DiscreteMin(最小値)
- DiscreteMax(最大値)
- CumulativeSum(合計値)
指定できるHKStatisticsOptionsはデータによって異なります。HKStatisticsOptionsはビットフラグで管理されているので、複数立てることが可能です。
let statisticsOptions: HKStatisticsOptions = HKStatisticsOptions.DiscreteAverage | HKStatisticsOptions.DiscreteMin | HKStatisticsOptions.DiscreteMax
例えば上記のHKStatisticsOptionsを指定すると、全ての体温の平均・最小値・最大値を取得することができます。
HKStatisticsCollectionQuery
1日毎の集計を行いたい場合などは、こちらを使用すると良いでしょう。
HKStatisticsCollectionQuery(quantityType: HKQuantityType!, quantitySamplePredicate: NSPredicate!, options: HKStatisticsOptions, anchorDate: NSDate!, intervalComponents: NSDateComponents!)
anchorDate: NSDate!とintervalComponents: NSDateComponents!を組み合わせる事によって、特定の日付から決められた間隔の集計をすることができます。
例えば、今月の毎日の体温の統計情報を取る事が可能です。
HKSourceQuery
HKSourceQuery(sampleType: HKSampleType!, samplePredicate objectPredicate: NSPredicate!, completionHandler: ((HKSourceQuery!, NSSet!, NSError!) -> Void)!)
HKCorrelationQuery
HKCorrelationQuery(type correlationType: HKCorrelationType!, predicate: NSPredicate!, samplePredicates: [NSObject : AnyObject]!, completion: ((HKCorrelationQuery!, [AnyObject]!, NSError!) -> Void)!)